﻿using System;
using System.ComponentModel;
using System.Windows.Data;

namespace NthDownload.Common.Validation
{
    public class BindingGroupValidator : INotifyPropertyChanged, IDisposable
    {
        #region INotifyPropertyChanged Implementation

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion INotifyPropertyChanged Implementation

        #region Class Members

        private BindingGroup _bindingGroup;

        #endregion Class Members

        #region Constructor

        public BindingGroupValidator()
        {
            BindingGroup = null;
        }

        public BindingGroupValidator(BindingGroup bindingGroup)
        {
            BindingGroup = bindingGroup;
        }

        #endregion Constructor

        #region Properties

        /// <summary>
        /// The binding group the validator should validate against
        /// </summary>
        public BindingGroup BindingGroup
        {
            get
            {
                return _bindingGroup;
            }
            set
            {
                _bindingGroup = value;
                OnPropertyChanged("BindingGroup");
            }
        }

        #endregion Properties

        /// <summary>
        /// Validate binding expressions explicitly set to be in this binding group, only validation rules with ValidationStep property set to RawProposedValue, ConvertedProposedValue, or UpdatedValue
        /// </summary>
        public bool ValidateBindingExpressionsWithUpdate()
        {
            if (BindingGroup == null) return true;
            bool isValid = true;
            foreach (BindingExpression be in BindingGroup.BindingExpressions)
            {
                if (be.ParentBinding.BindingGroupName == BindingGroup.Name)
                {
                    be.UpdateSource();
                    if (be.ValidationError != null)
                    {
                        isValid = false;
                    }
                }
            }

            return isValid;
        }

        /// <summary>
        /// Validate binding expressions explicitly set to be in this binding group, only validation rules with ValidationStep property set to RawProposedValue or ConvertedProposedValue.
        /// </summary>
        public bool ValidateBindingExpressionsWithOutUpdate()
        {
            if (BindingGroup == null) return true;
            bool isValid = true;
            foreach (BindingExpression be in BindingGroup.BindingExpressions)
            {
                if (be.ParentBinding.BindingGroupName == BindingGroup.Name && !be.ValidateWithoutUpdate())
                {
                    isValid = false;
                }
            }

            return isValid;
        }

        #region IDisposable

        public void Dispose()
        {
            if (BindingGroup == null) return;
            BindingGroup = null;
        }

        #endregion IDisposable
    }
}
